Skip to content

feat: migrate tracing web client from deprecated to new API endpoints#4571

Closed
GanJiaKouN16 wants to merge 1 commit into
Agenta-AI:mainfrom
GanJiaKouN16:fix/migrate-tracing-endpoints-4492
Closed

feat: migrate tracing web client from deprecated to new API endpoints#4571
GanJiaKouN16 wants to merge 1 commit into
Agenta-AI:mainfrom
GanJiaKouN16:fix/migrate-tracing-endpoints-4492

Conversation

@GanJiaKouN16
Copy link
Copy Markdown

Summary

Migrates 4 of 5 deprecated /tracing/* endpoints to their canonical replacements. The analytics endpoint (/tracing/spans/analytics) is deferred per issue author's recommendation.

Endpoint migrations

Legacy New Change Type
POST /tracing/spans/query POST /spans/query URL + focus param removed (always returns flat spans)
GET /tracing/traces/{id} GET /traces/{id} URL + response shape (traces record → single trace object)
DELETE /tracing/traces/{id} DELETE /traces/{id} URL-only
POST /tracing/sessions/query POST /spans/sessions/query URL-only

Files changed (8)

New Zod schemas (web/packages/agenta-entities/src/trace/core/schema.ts):

  • traceResponseSchema — for GET /traces/{id}: {count, trace: {trace_id, spans}}
  • traceIdResponseSchema — for DELETE /traces/{id}: {count, trace_id}
  • sessionIdsResponseSchema — for POST /spans/sessions/query: {count, session_ids, windowing}

Entities API (web/packages/agenta-entities/src/trace/api/api.ts):

  • fetchAllPreviewTracesPOST /spans/query, strips focus param, always returns SpansResponse
  • fetchPreviewTraceGET /traces/{id}, returns TraceResponse
  • deletePreviewTraceDELETE /traces/{id}, returns TraceIdResponse
  • fetchSessionsPOST /spans/sessions/query, returns SessionIdsResponse

New helpers (web/packages/agenta-entities/src/trace/api/helpers.ts):

  • isTraceResponse — type guard for new single-trace response
  • transformTraceResponseToTree — builds span tree from TraceResponse

OSS API (web/oss/src/services/tracing/api/index.ts):

  • URL updates for all 4 endpoints
  • focus param stripped from fetchAllPreviewTraces and fetchAllPreviewTracesWithMeta

Annotation controller (web/packages/agenta-annotation/src/state/controllers/annotationFormController.ts):

  • Updated to handle new {trace: {trace_id, spans}} shape with legacy fallback

Backward compatibility

  • Existing consumer branching logic (isTracesResponse/isSpansResponse) continues to work
  • POST /spans/query always returns SpansResponse now, so the isTracesResponse branch becomes dead code for list queries (harmless)
  • normalizeTracesResponse() in drawer stores already handles .trace shape
  • Analytics endpoint stays on /tracing/spans/analytics (deferred to separate PR)

Fixes #4492

Migrate 4 of 5 deprecated /tracing/* endpoints to their canonical
replacements. The analytics endpoint (/tracing/spans/analytics) is
deferred per issue author's recommendation.

Endpoint migrations:
- POST /tracing/spans/query → POST /spans/query
- GET /tracing/traces/{id} → GET /traces/{id}
- DELETE /tracing/traces/{id} → DELETE /traces/{id}
- POST /tracing/sessions/query → POST /spans/sessions/query

Changes:
- Add traceResponseSchema, traceIdResponseSchema, sessionIdsResponseSchema
  Zod schemas for the new response shapes
- Update entities API (api.ts) to hit new endpoints with new response
  parsing. POST /spans/query now always returns flat SpansResponse
  (focus param removed). GET /traces/{id} returns single TraceResponse.
- Update OSS API (index.ts) to hit new URLs, strip focus param
- Update annotationFormController to handle new trace response shape
  ({trace: {trace_id, spans}} instead of {traces: {id: {spans}}})
- Add isTraceResponse type guard and transformTraceResponseToTree helper
- Existing consumer branching logic (isTracesResponse/isSpansResponse)
  continues to work — POST /spans/query always returns SpansResponse
  so isTracesResponse branch becomes dead code for list queries

Fixes Agenta-AI#4492
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 6, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 6, 2026

Someone is attempting to deploy a commit to the agenta projects Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


GanJiaKouN16 seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@dosubot dosubot Bot added enhancement New feature or request typescript labels Jun 6, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 6, 2026

Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine.

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved trace response validation and data extraction to handle new response formats correctly.
    • Enhanced backward compatibility during API endpoint migration to ensure seamless operation.
  • Refactor

    • Updated trace querying to use streamlined API endpoints with standardized response schemas.
    • Strengthened type safety for trace and session data with enhanced validation.

Walkthrough

This pull request migrates the tracing API client from deprecated /tracing/* endpoints to canonical /spans/* and /traces/* routes. It introduces new response schemas, updates API contracts to remove the focus parameter and return typed responses instead of raw data, implements these changes across the OSS service, and adds backward compatibility support for legacy response shapes during rollout.

Changes

Trace API Endpoint & Response Shape Migration

Layer / File(s) Summary
Response schema definitions and type exports
web/packages/agenta-entities/src/trace/core/schema.ts, web/packages/agenta-entities/src/trace/core/index.ts, web/packages/agenta-entities/src/trace/index.ts
New Zod response schemas added for GET /traces/{id} returning TraceResponse (single trace with flat spans), DELETE /traces/{id} returning TraceIdResponse, and POST /spans/sessions/query returning SessionIdsResponse. Re-exported through core and top-level trace modules.
Response validation type guards and tree builders
web/packages/agenta-entities/src/trace/api/helpers.ts, web/packages/agenta-entities/src/trace/api/index.ts
New isTraceResponse type guard added for the single-trace response shape. isSpansResponse strengthened to validate spans is an array. New transformTraceResponseToTree helper builds span trees from TraceResponse.trace.spans. Legacy tree builder refactored to share internal logic. Re-exported through api module.
Core API contract and endpoint routing
web/packages/agenta-entities/src/trace/api/api.ts
TraceQueryParams removes focus field. fetchAllPreviewTraces returns SpansResponse | null instead of union with TracesResponse. fetchPreviewTrace calls GET /traces/{id} and returns TraceResponse | null instead of TracesResponse | null. deletePreviewTrace calls DELETE /traces/{id} and returns typed TraceIdResponse | null instead of raw unknown. fetchSessions calls POST /spans/sessions/query and returns typed SessionIdsResponse | null instead of raw unknown.
OSS tracing service endpoint migrations
web/oss/src/services/tracing/api/index.ts
Endpoint URLs updated: fetchAllPreviewTraces and fetchAllPreviewTracesWithMeta migrate to /spans/query without focus parameter, fetchPreviewTrace to /traces/{traceId}, deletePreviewTrace to /traces/{traceId}, and fetchSessions to /spans/sessions/query.
Consumer backward compatibility during rollout
web/packages/agenta-annotation/src/state/controllers/annotationFormController.ts
resolveTraceLinkSpanId updated to support both new traceResponse.trace (single object) and legacy traceResponse.traces (record) response shapes, with fallback logic using dash-less or original traceId keys.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: migrate tracing web client from deprecated to new API endpoints' accurately and clearly summarizes the main change—migrating the web client from deprecated /tracing/* endpoints to new canonical endpoints.
Description check ✅ Passed The description provides comprehensive details about the migration including endpoint mappings, schema changes, and backward-compatibility notes, all directly related to the changeset.
Linked Issues check ✅ Passed The PR successfully addresses the primary objective in issue #4492 by migrating 4 of 5 deprecated endpoints with updated schemas, helpers, and API consumers, while deferring the analytics endpoint as recommended.
Out of Scope Changes check ✅ Passed All changes directly support the endpoint migration goals: schema definitions, API client updates, helper functions, and consumer updates align with the PR objectives and issue requirements.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 60.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
web/packages/agenta-entities/src/trace/api/api.ts (2)

41-48: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

TraceQueryParams still accepts deprecated keys.

Removing focus from the named fields does not make stale callers fail because the [key: string]: unknown catch-all still accepts {focus: "trace"} and any other legacy payload fields. That weakens the #4492 migration: callers can keep compiling while this function silently drops focus and always returns flat spans. Please tighten this type to the actual supported request shape so legacy callers break at compile time.

Suggested direction
 export interface TraceQueryParams {
     size?: number
     format?: string
     filter?: string | Record<string, unknown>
     oldest?: string
     newest?: string
     cursor?: string
-    [key: string]: unknown
 }

62-97: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Use the Fern client for these migrated endpoints.

These new /spans/* and /traces/* calls are still hand-built with raw axios, string URLs, and manual query serialization. That leaves this package with a second API surface to keep in sync during the migration. Please switch these functions to getAgentaSdkClient({host: getAgentaApiUrl()}) and pass query params via {queryParams: {...}} instead of interpolating them into the URL.

As per coding guidelines, "All new frontend API code must go through the Fern-generated client, not raw axios", "Use getAgentaSdkClient({host: getAgentaApiUrl()}) — it is a lazy singleton, share it across calls", and "Pass query params via {queryParams: {...}}, NOT axios's {params: {...}}."

Also applies to: 110-149, 177-210

Source: Coding guidelines

web/oss/src/services/tracing/api/index.ts (1)

19-57: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Avoid adding a second manual client for the canonical tracing endpoints.

This file reimplements the same /spans/* and /traces/* migration with fetchJson, ad-hoc payload shaping, and untyped Record<string, any> params. That duplicates web/packages/agenta-entities/src/trace/api/api.ts, lets legacy keys like focus keep flowing through type-checking here, and raises the odds that the next contract change lands in only one layer. Please route these OSS calls through the shared Fern client instead of extending the legacy wrapper.

As per coding guidelines, "All new frontend API code must go through the Fern-generated client, not raw axios", "Use getAgentaSdkClient({host: getAgentaApiUrl()}) — it is a lazy singleton, share it across calls", and "Pass query params via {queryParams: {...}}, NOT axios's {params: {...}}."

Also applies to: 91-205

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5093432f-fff7-4beb-a28e-c2367296fbfb

📥 Commits

Reviewing files that changed from the base of the PR and between 98b8a9d and 547538b.

📒 Files selected for processing (8)
  • web/oss/src/services/tracing/api/index.ts
  • web/packages/agenta-annotation/src/state/controllers/annotationFormController.ts
  • web/packages/agenta-entities/src/trace/api/api.ts
  • web/packages/agenta-entities/src/trace/api/helpers.ts
  • web/packages/agenta-entities/src/trace/api/index.ts
  • web/packages/agenta-entities/src/trace/core/index.ts
  • web/packages/agenta-entities/src/trace/core/schema.ts
  • web/packages/agenta-entities/src/trace/index.ts

Comment on lines +641 to +646
const traceEntry =
traceResponse?.trace ?? (() => {
const traceKey = traceId.replace(/-/g, "")
return (traceResponse as any)?.traces?.[traceKey] ??
(traceResponse as any)?.traces?.[traceId]
})()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Type the legacy fallback path instead of casting to any

This keeps the rollout fallback while preserving strict typing in package code.

Suggested fix
+        type LegacyTraceResponse = {
+            traces?: Record<string, {spans?: Record<string, TraceSpan>}>
+        }
         const traceEntry =
             traceResponse?.trace ?? (() => {
                 const traceKey = traceId.replace(/-/g, "")
-                return (traceResponse as any)?.traces?.[traceKey] ??
-                    (traceResponse as any)?.traces?.[traceId]
+                const legacy = traceResponse as LegacyTraceResponse | null
+                return legacy?.traces?.[traceKey] ?? legacy?.traces?.[traceId]
             })()

As per coding guidelines: web/packages/**/*.{ts,tsx} requires “Do not use any types in package code; follow strict typing rules.”

Source: Coding guidelines

Comment on lines +37 to +38
return typeof data === "object" && data !== null && "spans" in data && Array.isArray((data as any).spans)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove any from the response type guard

Use a typed unknown narrowing instead of (data as any) in package code.

Suggested fix
 export const isSpansResponse = (data: unknown): data is SpansResponse => {
-    return typeof data === "object" && data !== null && "spans" in data && Array.isArray((data as any).spans)
+    if (typeof data !== "object" || data === null) return false
+    return Array.isArray((data as {spans?: unknown}).spans)
 }

As per coding guidelines: web/packages/**/*.{ts,tsx} requires “Do not use any types in package code; follow strict typing rules.”

Source: Coding guidelines

Comment on lines +242 to +251
export const traceResponseSchema = z.object({
count: z.number().optional().default(0),
trace: z
.object({
trace_id: z.string().optional().nullable(),
spans: z.record(z.string(), traceSpanSchema).optional().nullable(),
})
.optional()
.nullable(),
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Legacy fallback data is stripped at the parse boundary

traceResponseSchema currently omits legacy traces, so parsed output drops that key before resolveTraceLinkSpanId can use its fallback path. This breaks the intended rollout compatibility if an environment still serves legacy shape.

Suggested fix
 export const traceResponseSchema = z.object({
     count: z.number().optional().default(0),
     trace: z
         .object({
             trace_id: z.string().optional().nullable(),
             spans: z.record(z.string(), traceSpanSchema).optional().nullable(),
         })
         .optional()
         .nullable(),
+    // Keep legacy shape during rollout so downstream fallback can still read it.
+    traces: z
+        .record(
+            z.string(),
+            z.object({
+                spans: z.record(z.string(), traceSpanSchema),
+            }),
+        )
+        .optional(),
 })

Based on learnings from PR objectives: backward-compatible fallback for legacy response shapes should be preserved during rollout.

@ardaerzin
Copy link
Copy Markdown
Contributor

closing as duplicate of #4573

@ardaerzin ardaerzin closed this Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:L This PR changes 100-499 lines, ignoring generated files. typescript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move tracing away from deprecated (and then legacy) endpoints.

3 participants